﻿#region License
/*
Copyright (c) 2009, Open University of the Netherlands
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided 
that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the 
  following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 
  the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of Open University of the Netherlands nor the names of its contributors may be 
  used to endorse or promote products derived from this software without specific prior written 
  permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
*/
#endregion

namespace EwbDesigner.NET.Editors
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;

    //As Main Control add a Page Control without tabs.
    //So we can design it easily for each possibility...
    //Add a TypeConverter for extra checks....
    //SEE http://msdn.microsoft.com/en-us/library/ms171840.aspx
    /* Standard Editors...
        System.ComponentModel.Design..::.BinaryEditor
        System.ComponentModel.Design..::.CollectionEditor
        System.ComponentModel.Design..::.DateTimeEditor
        System.ComponentModel.Design..::.MultilineStringEditor
        System.ComponentModel.Design..::.ObjectSelectorEditor
        System.Drawing.Design..::.ColorEditor
        System.Drawing.Design..::.ContentAlignmentEditor
        System.Drawing.Design..::.CursorEditor
        System.Drawing.Design..::.FontEditor
        System.Drawing.Design..::.FontNameEditor
        System.Drawing.Design..::.IconEditor
        System.Drawing.Design..::.ImageEditor
        System.Messaging.Design..::.QueuePathEditor
        System.Web.UI.Design..::.ConnectionStringEditor
        System.Web.UI.Design..::.DataBindingCollectionEditor
        System.Web.UI.Design..::.ExpressionsCollectionEditor
        System.Web.UI.Design..::.UrlEditor
        System.Web.UI.Design.WebControls..::.DataControlFieldTypeEditor
        System.Web.UI.Design.WebControls..::.DataGridColumnCollectionEditor
        System.Web.UI.Design.WebControls..::.DataPagerFieldTypeEditor
        System.Web.UI.Design.WebControls..::.MenuBindingsEditor
        System.Web.UI.Design.WebControls..::.MenuItemCollectionEditor
        System.Web.UI.Design.WebControls..::.ParameterCollectionEditor
        System.Web.UI.Design.WebControls..::.RegexTypeEditor
        System.Web.UI.Design.WebControls..::.TreeNodeCollectionEditor
        System.Web.UI.Design.WebControls..::.TreeViewBindingsEditor
        System.Web.UI.Design..::.XmlFileEditor
        System.Windows.Forms.Design..::.AnchorEditor
        System.Windows.Forms.Design..::.BorderSidesEditor
        System.Windows.Forms.Design..::.DockEditor
        System.Windows.Forms.Design..::.FileNameEditor
        System.Windows.Forms.Design..::.FolderNameEditor
        System.Windows.Forms.Design..::.ShortcutKeysEditor
        System.Workflow.ComponentModel.Design..::.BindUITypeEditor
        System.Workflow.ComponentModel.Design..::.TypeBrowserEditor
    */

    /// <summary>
    /// Removes Whitespace from String Properties.
    /// </summary>
    //public class WhiteSpaceConverter : TypeConverter
    //{
    //    #region Methods
    //    // Overrides the CanConvertFrom method of TypeConverter.
    //    // The ITypeDescriptorContext interface provides the context for the
    //    // conversion. Typically, this interface is used at design time to
    //    // provide information about the design-time container.
    //    public override bool CanConvertFrom(ITypeDescriptorContext context,
    //        Type sourceType)
    //    {
    //        if (sourceType == typeof(String))
    //        {
    //            return true;
    //        }
    //        return base.CanConvertFrom(context, sourceType);
    //    }
    //    // Overrides the ConvertFrom method of TypeConverter.
    //    public override object ConvertFrom(ITypeDescriptorContext context,
    //        CultureInfo culture, object value)
    //    {
    //        if (value is String)
    //        {
    //            //    string[] v = ((string)value).Split(new char[] { ',' });
    //            //    return new Point(int.Parse(v[0]), int.Parse(v[1]));
    //            return value.ToString().Replace(' ', '_');
    //        }
    //        return base.ConvertFrom(context, culture, value);
    //    }
    //    // Overrides the ConvertTo method of TypeConverter.
    //    public override object ConvertTo(ITypeDescriptorContext context,
    //        CultureInfo culture, object value, Type destinationType)
    //    {
    //        if (destinationType == typeof(String))
    //        {
    //            //return ((Point)value).X + "," + ((Point)value).Y;
    //            return value.ToString().Replace(' ', '_');
    //        }
    //        return base.ConvertTo(context, culture, value, destinationType);
    //    }
    //}

    //View Control...
    public partial class XmlAttributeItemEditorControl : UserControl
    {
        #region Fields

        private static Char[] ListSeparator = CultureInfo.CurrentCulture.TextInfo.ListSeparator.ToCharArray();
        static Int32 fLastChecked = -1;

        private XmlAttributeItem XmlAttributeItemValue;
        private IWindowsFormsEditorService editorService = null;

        #endregion Fields

        #region Constructors

        // This constructor takes a MarqueeLightShape value from the
        // design-time environment, which will be used to display
        // the initial state.
        public XmlAttributeItemEditorControl(XmlAttributeItem XmlAttributeItemValue,
            IWindowsFormsEditorService editorService)
        {
            // This call is required by the designer.
            InitializeComponent();

            // Cache the XsdCacheItem value provided by the
            // design-time environment.
            this.XmlAttributeItemValue = XmlAttributeItemValue;

            // Cache the reference to the editor service.
            this.editorService = editorService;

            switch (this.XmlAttributeItemValue.editor)
            {
                case XsdAttributeEditor.Enumeration:
                    {
                        panelManager1.SelectedPanel = EnumeratePanel;

                        checkedListBox1.Items.Clear();
                        checkedListBox1.CheckOnClick = true;
                        checkedListBox1.SelectionMode = SelectionMode.One;

                        foreach (String s in this.XmlAttributeItemValue.values)
                        {
                            checkedListBox1.Items.Add(s);
                        }

                        if (checkedListBox1.Items.IndexOf(XmlAttributeItemValue.value) != -1)
                        {
                            checkedListBox1.SetItemChecked(checkedListBox1.Items.IndexOf(XmlAttributeItemValue.value), true);
                        }

                        break;
                    }
                case XsdAttributeEditor.ArrayofString:
                    {
                        panelManager1.SelectedPanel = textPanel;

                        textBox1.Text = XmlAttributeItemValue.value;

                        break;
                    }
                case XsdAttributeEditor.Html:
                    {
                        panelManager1.SelectedPanel = htmlPanel;
                        
                        //htmlEditor1.Navigate("About:Blank");
                        htmlEditor1.Body = XmlAttributeItemValue.value;

                        break;
                    }
            }
        }

        #endregion Constructors

        #region Properties

        public String Result
        {
            get
            {
                switch (this.XmlAttributeItemValue.editor)
                {
                    case XsdAttributeEditor.Enumeration:
                        if (checkedListBox1.CheckedItems.Count == 1)
                        {
                            return checkedListBox1.CheckedItems[0].ToString();
                        }
                        return "**error**";

                    case XsdAttributeEditor.ArrayofString:
                        return textBox1.Text.Trim();

                    case XsdAttributeEditor.Html:
                        return htmlEditor1.Body;

                    default:
                        return "**error**";
                }
            }
        }

        // XmlAttributeItem is the property for which this control provides
        // a custom user interface in the Properties window.
        public XmlAttributeItem XmAttributelItem
        {
            get
            {
                return this.XmlAttributeItemValue;
            }

            set
            {
                if (this.XmlAttributeItemValue != value)
                {
                    this.XmlAttributeItemValue = value;
                }
            }
        }

        #endregion Properties

        #region Event Handlers

        /// <summary>
        /// Make this CheckedListBox work like a RadioGroup.
        /// 
        /// See http://bytes.com/topic/visual-basic-net/answers/351844-constrain-numbers-item-check-checkedlistbox
        /// See http://www.experts-exchange.com/Programming/Misc/Q_21365446.html (uses SelectedIndexChanged)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (e.Index != fLastChecked && fLastChecked != -1)
            {
                checkedListBox1.SetItemChecked(fLastChecked, false);
            }
            fLastChecked = e.Index;
        }

        //protected override void OnPaint(PaintEventArgs e)
        //{
        //    base.OnPaint(e);
        //
        //    Custom paint away...
        //}

        #endregion Event Handlers

    }

    public class CustomStringCollectionEditor : UITypeEditor
    {
        #region Fields

        private static String ListSeparator = CultureInfo.CurrentCulture.TextInfo.ListSeparator;

        private IWindowsFormsEditorService editorService = null;

        #endregion Fields

        #region Properties

        public override bool IsDropDownResizable
        {
            get { return true; }
        }

        #endregion Properties

        #region Methods

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (provider != null)
            {
                editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
            }

            if (editorService != null)
            {
                XmlAttributeItemEditorControl selectionControl = new XmlAttributeItemEditorControl((XmlAttributeItem)value, editorService);

                editorService.DropDownControl(selectionControl);

                value = selectionControl.Result;// selectionControl.XmAttributelItem;
            }

            return value;
        }

        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            // Specify a modal UITypeEditor
            return UITypeEditorEditStyle.DropDown;
        }

        #endregion Methods
    }

    public class CustomHtmlEditor : UITypeEditor
    {
        #region Fields

        private static String ListSeparator = CultureInfo.CurrentCulture.TextInfo.ListSeparator;

        private IWindowsFormsEditorService editorService = null;

        #endregion Fields

        #region Properties

        public override bool IsDropDownResizable
        {
            get { return true; }
        }

        #endregion Properties

        #region Methods

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (provider != null)
            {
                editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
            }

            if (editorService != null)
            {
                XmlAttributeItemEditorControl selectionControl = new XmlAttributeItemEditorControl((XmlAttributeItem)value, editorService);

                editorService.DropDownControl(selectionControl);

                value = selectionControl.Result;// selectionControl.XmAttributelItem;
            }

            return value;
        }

        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            // Specify a modal UITypeEditor
            return UITypeEditorEditStyle.DropDown;
        }

        #endregion Methods
    }

    // This class demonstrates the use of a custom UITypeEditor.
    // It allows the MarqueeBorder control's LightShape property
    // to be changed at design time using a customized UI element
    // that is invoked by the Properties window. The UI is provided
    // by the LightShapeSelectionControl class.
    internal class CustomXsdCacheItemEditor : UITypeEditor
    {
        #region Fields

        private IWindowsFormsEditorService editorService = null;

        #endregion Fields

        #region Properties

        public override bool IsDropDownResizable
        {
            get { return true; }
        }

        #endregion Properties

        #region Methods

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (provider != null)
            {
                editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
            }

            if (editorService != null)
            {
                XmlAttributeItemEditorControl selectionControl = new XmlAttributeItemEditorControl((XmlAttributeItem)value, editorService);

                editorService.DropDownControl(selectionControl);

                value = selectionControl.Result;// selectionControl.XmAttributelItem;
            }

            return value;
        }

        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {
            //Have this depend on the property type, other values Modal and None ...
            return UITypeEditorEditStyle.DropDown;
        }

        /// <summary>
        /// Indicates whether the UITypeEditor supports painting a 
        /// representation of a property's value.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override bool GetPaintValueSupported(ITypeDescriptorContext context)
        {
            return false;
        }

        /// <summary>
        /// Paints a representation of the value of an object using the specified System.Drawing.Design.PaintValueEventArgs.
        /// </summary>
        /// <param name="e"></param>
        public override void PaintValue(PaintValueEventArgs e)
        {
            //e.Graphics.DrawString(e.Value.ToString(), new Font("Arial", 8), new SolidBrush(Color.Black), e.Bounds);
        }

        #endregion Methods
    }
}